package cn.iocoder.springboot.labs.utils;

import org.springframework.web.multipart.MultipartFile;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;

public class ImageUtil {
    /**
     * 压缩 MultipartFile 图片文件，返回字节数组
     *
     * @param file       MultipartFile 对象
     * @param formatName 图片格式 (JPEG, PNG等)
     * @return 压缩后的图片字节数组
     */
    public static byte[] compressImage(MultipartFile file, String formatName) {
        return compressImage(file, formatName, 0.8f, null);
    }

    /**
     * 压缩 MultipartFile 图片文件，返回字节数组（带质量参数）
     *
     * @param file       MultipartFile 对象
     * @param formatName 图片格式
     * @param quality    压缩质量 (0.0-1.0)
     * @return 压缩后的图片字节数组
     */
    public static byte[] compressImage(MultipartFile file, String formatName, float quality) {
        return compressImage(file, formatName, quality, null);
    }

    /**
     * 压缩 MultipartFile 图片文件，返回字节数组（完整参数）
     *
     * @param file       MultipartFile 对象
     * @param formatName 图片格式
     * @param quality    压缩质量 (0.0-1.0)
     * @param maxSize    最大尺寸（宽高最大值，null表示保持原尺寸）
     * @return 压缩后的图片字节数组
     */
    public static byte[] compressImage(MultipartFile file, String formatName, Float quality, Integer maxSize) {
        // 检查文件是否为空
        if (file == null || file.isEmpty()) {
            throw new IllegalArgumentException("上传的文件为空");
        }

        // 检查文件类型
        System.out.println(file.getContentType());
        System.out.println(file.getName());
        System.out.println(file.getSize());
        System.out.println(file.getResource().getFilename());
        String contentType = file.getContentType();
        System.out.println("<UNK>" + contentType);
        if (contentType == null || !contentType.startsWith("image/")) {
            throw new IllegalArgumentException("文件不是图片类型: " + contentType);
        }

        try (InputStream inputStream = file.getInputStream();
             ByteArrayOutputStream output = new ByteArrayOutputStream()) {

            // 读取图片
            BufferedImage image = ImageIO.read(inputStream);
            if (image == null) {
                throw new IllegalArgumentException("无法读取图片数据，可能不是支持的图片格式");
            }

            System.out.println("原始图片尺寸: " + image.getWidth() + "x" + image.getHeight());
            System.out.println("原始文件大小: " + file.getSize() + " 字节");

            // 调整图片尺寸（如果需要）
            if (maxSize != null && maxSize > 0) {
                image = resizeImage(image, maxSize);
                System.out.println("调整后尺寸: " + image.getWidth() + "x" + image.getHeight());
            }

            // 压缩图片
            if ("JPEG".equalsIgnoreCase(formatName) && quality != null) {
                compressJpegWithQuality(image, output, quality);
            } else {
                // 其他格式直接保存
                ImageIO.write(image, formatName, output);
            }

            byte[] compressedBytes = output.toByteArray();
            System.out.println("压缩后大小: " + compressedBytes.length + " 字节");
            System.out.println("压缩比例: " + String.format("%.1f%%",
                    (1 - (double) compressedBytes.length / file.getSize()) * 100));

            return compressedBytes;

        } catch (IOException e) {
            throw new RuntimeException("图片压缩失败: " + e.getMessage(), e);
        }
    }

    /**
     * 从字节数组压缩图片
     */
    public static byte[] compressImage(byte[] imageBytes, String formatName, Float quality, Integer maxSize) {
        try (ByteArrayInputStream input = new ByteArrayInputStream(imageBytes);
             ByteArrayOutputStream output = new ByteArrayOutputStream()) {

            BufferedImage image = ImageIO.read(input);
            if (image == null) {
                throw new IllegalArgumentException("无法读取图片数据");
            }

            // 调整图片尺寸（如果需要）
            if (maxSize != null && maxSize > 0) {
                image = resizeImage(image, maxSize);
            }

            // 压缩图片
            if ("JPEG".equalsIgnoreCase(formatName) && quality != null) {
                compressJpegWithQuality(image, output, quality);
            } else {
                ImageIO.write(image, formatName, output);
            }

            return output.toByteArray();

        } catch (IOException e) {
            throw new RuntimeException("图片压缩失败", e);
        }
    }

    /**
     * 调整图片尺寸
     */
    private static BufferedImage resizeImage(BufferedImage originalImage, int maxSize) {
        int originalWidth = originalImage.getWidth();
        int originalHeight = originalImage.getHeight();

        // 如果图片已经小于最大尺寸，直接返回
        if (originalWidth <= maxSize && originalHeight <= maxSize) {
            return originalImage;
        }

        // 计算新尺寸
        int newWidth, newHeight;
        if (originalWidth > originalHeight) {
            newWidth = maxSize;
            newHeight = (int) ((double) originalHeight / originalWidth * maxSize);
        } else {
            newHeight = maxSize;
            newWidth = (int) ((double) originalWidth / originalHeight * maxSize);
        }

        // 确保最小尺寸为1
        newWidth = Math.max(1, newWidth);
        newHeight = Math.max(1, newHeight);

        // 创建新图片
        BufferedImage resizedImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = resizedImage.createGraphics();

        // 设置渲染参数
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        // 绘制白色背景（针对透明图片转JPEG的情况）
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, newWidth, newHeight);

        g.drawImage(originalImage, 0, 0, newWidth, newHeight, null);
        g.dispose();

        return resizedImage;
    }

    /**
     * JPEG格式带质量压缩
     */
    private static void compressJpegWithQuality(BufferedImage image, OutputStream output, float quality) throws IOException {
        // 转换图片类型为RGB（确保JPEG兼容）
        BufferedImage rgbImage = new BufferedImage(
                image.getWidth(),
                image.getHeight(),
                BufferedImage.TYPE_INT_RGB
        );
        Graphics2D g = rgbImage.createGraphics();
        g.drawImage(image, 0, 0, null);
        g.dispose();

        // 获取JPEG写入器
        ImageWriter writer = ImageIO.getImageWritersByFormatName("JPEG").next();

        try (ImageOutputStream ios = ImageIO.createImageOutputStream(output)) {
            writer.setOutput(ios);

            ImageWriteParam param = writer.getDefaultWriteParam();

            // 设置压缩模式和质量
            param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
            param.setCompressionQuality(quality);

            // 写入图片
            writer.write(null, new IIOImage(rgbImage, null, null), param);
        } finally {
            writer.dispose();
        }
    }

    /**
     * 获取图片信息
     */
    public static String getImageInfo(MultipartFile file) {
        try (InputStream inputStream = file.getInputStream()) {
            BufferedImage image = ImageIO.read(inputStream);
            if (image != null) {
                return String.format("尺寸: %dx%d, 类型: %s, 大小: %.1fKB",
                        image.getWidth(), image.getHeight(),
                        file.getContentType(),
                        file.getSize() / 1024.0);
            }
        } catch (IOException e) {
            // 忽略错误
        }
        return "无法获取图片信息";
    }
}
